home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
167_01
/
spline.c
< prev
next >
Wrap
Text File
|
1985-11-13
|
18KB
|
735 lines
/*
HEADER: CUG
TITLE: SPLINE.C - Interpolate Smooth Curve;
VERSION: 3.00;
DATE: 09/26/86;
DESCRIPTION: "SPLINE takes pairs of numbers from the standard
input as abscissae and ordinates of a function.
It produces a similar set, which is approximately
equally spaced and includes the input set, on the
standard output. The cubic spline output has two
continuous derivatives and sufficiently many
points to look smooth when plotted.";
KEYWORDS: spline, graphics, plot, filter, UNIX;
SYSTEM: ANY;
FILENAME: SPLINE.DOC;
WARNINGS: NONE;
CRC: xxxx
SEE-ALSO: SPLINE.C;
AUTHORS: Ian Ashdown - byHeart Software;
COMPILERS: ANY;
REFERENCES: AUTHORS: Bell Laboratories;
TITLE: UNIX Programmer's Manual, Volume 1
p. 145, Holt, Rinehart and Winston;
AUTHORS: R.W. Hamming;
TITLE: Numerical Methods for Scientists and
Engineers, 2nd Edition
pp. 349 - 355, McGraw-Hill (1973);
AUTHORS: Forsythe, Malcolm & Moler;
TITLE: Computer Methods for Mathematical
Computations
pp. 70 - 83, Prentice-Hall;
ENDREF
*/
/*-------------------------------------------------------------*/
/* SPLINE.C - Interpolate Smooth Curve
*
* Version 3.00 September 26th, 1986
*
* Modifications:
*
* V1.00 (85/11/01) - beta test release
* V2.00 (85/12/25) - general revision
* V2.01 (86/09/13) - corrected command-line option bug for
* Microsoft C compiler
* V3.00 (86/09/26) - added non-uniform abscissa spacing
* capability
*
* Copyright 1985,1986: Ian Ashdown
* byHeart Software
* 620 Ballantree Road
* West Vancouver, B.C.
* Canada V7S 1W3
*
* This program may be copied for personal, non-commercial use
* only, provided that the above copyright notice is included in
* all copies of the source code. Copying for any other use
* without previously obtaining the written permission of the
* author is prohibited.
*
* Synopsis: SPLINE [option] ...
*
* Description: SPLINE takes pairs of numbers from the standard
* input as abscissae and ordinates of a function.
* (A minimum of four pairs is required.) It
* produces a similar set, which is approximately
* equally spaced and includes the input set, on the
* standard output. The cubic spline output (R.W.
* Hamming, "Numerical Methods for Scientists and
* Engineers", 2nd ed. 349ff) has two continuous
* derivatives and sufficiently many points to look
* smooth when plotted.
*
* The following options are recognized, each as a
* separate argument:
*
* -a Supply abscissae automatically (they are
* missing from the input); spacing is given by
* the next argument or is assumed to be 1 if
* next argument is not a number.
*
* -k The constant "k" is used in the boundary
* value computation
*
* y " = ky " , y " = ky "
* 0 1 n n-1
*
* is set by the next argument. By default,
* k = 0. A value of k = 0.5 often results in a
* smoother curve at the endpoints than the
* default value. Negative values for k are not
* allowed. Cannot be used with -p option.
*
* -n Next argument (which must be an integer)
* specifies the number of intervals that are to
* occur between the lower and upper "x" limits.
* If -n option is not given, default spacing is
* 100 intervals.
*
* -p Make output periodic, i.e. match derivatives
* at ends. First and last input values must
* agree. Cannot be used with -k option.
*
* -x Next 1 (or 2) arguments are lower (and upper)
* "x" limits. Normally these limits are
* calculated from the data. Automatic abscissae
* start at lower limit (default 0). If either
* argument is outside of the range of
* abscissae, it is ignored.
*
* Diagnostics: When data is not strictly monotone in "x", SPLINE
* reproduces the input without interpolating extra
* points.
*
* Bugs: A limit of 1000 input points is silently
* enforced.
*
* The -n option has not been implemented in
* accordance with the "UNIX Programmer's Manual"
* specification. This was done to avoid ambiguities
* when the -n option follows the -x option with one
* argument.
*
* At certain negative values for the -k option (for
* example, k equals -4.0), the curve becomes
* discontinuous. The -k option value has thus been
* arbitrarily constrained to be greater than or
* equal to zero.
*
* Credits: The above description is a reworded and expanded
* version of that appearing in the "UNIX Programmer's
* Manual", copyright 1979, 1983 Bell Laboratories.
*/
/*** Definitions ***/
#define FALSE 0
#define TRUE 1
#define MAX_SIZE 1000 /* Input point array limit */
#define ILL_ARG 0 /* Error codes */
#define ILL_CMB 1
#define ILL_KVL 2
#define ILL_NVL 3
#define ILL_OPT 4
#define ILL_XVL 5
#define INS_INP 6
#define MIS_KVL 7
#define MIS_NVL 8
#define MIS_XVL 9
#define MIS_YVL 10
#define NMT_ORD 11
#define SQUARE(a) a*a
#define CUBE(a) a*a*a
/*** Typedefs ***/
typedef int BOOL; /* Boolean flag */
/*** Include Files ***/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
/*** Main Body of Program ***/
int main(argc,argv)
int argc;
char **argv;
{
int n = 0,
i,
j,
n_val = 0,
atoi();
float x[MAX_SIZE],
y[MAX_SIZE],
h[MAX_SIZE-1];
double a_val = 1.0,
k_val = 0.0,
x1_val = 0.0,
x2_val = 0.0,
x_intvl,
ix,
iy,
d2y[MAX_SIZE],
atof(),
spl_int();
char buffer[257],
*temp,
*gets();
BOOL aflag = FALSE, /* Command-line option flags */
kflag = FALSE,
pflag = FALSE,
x1flag = FALSE,
x2flag = FALSE,
is_float();
void spl_coeff(),
pspl_coeff(),
error();
/* Parse the command line for user-selected options */
while(--argc)
{
temp = *++argv;
if(*temp != '-') /* Check for legal option flag */
error(ILL_OPT,*argv);
else
{
temp++;
switch(toupper(*temp))
{
case 'A': /* "-a" option */
aflag = TRUE;
if(argc > 1 && is_float(*(argv+1)))
{
argc--;
argv++;
if((a_val = atof(*argv)) <= 0.00)
error(ILL_ARG,*argv);
}
break;
case 'K': /* "-k" option */
if(pflag == TRUE)
error(ILL_CMB,NULL);
kflag = TRUE;
if(argc > 1 && is_float(*(argv+1)))
{
argc--;
argv++;
k_val = atof(*argv);
if(k_val < 0.00)
error(ILL_KVL,*argv);
break;
}
else
error(MIS_KVL,NULL);
case 'N': /* "-n" option */
if(argc > 1)
{
argc--;
argv++;
if((n_val = atoi(*argv)) < 1)
error(ILL_NVL,*argv);
else
break;
}
else
error(MIS_NVL,NULL);
case 'P': /* "-p" option */
if(kflag == TRUE)
error(ILL_CMB,NULL);
pflag = TRUE;
break;
case 'X': /* "-x" option */
x1flag = TRUE;
if(argc > 1 && is_float(*(argv+1)))
{
argc--;
argv++;
x1_val = atof(*argv);
}
else
error(MIS_XVL,NULL);
if(argc > 1 && is_float(*(argv+1)))
{
x2flag = TRUE;
argc--;
argv++;
x2_val = atof(*argv);
if(x2_val <= x1_val)
error(ILL_XVL,x2_val);
}
break;
default: /* "-n" option */
error(ILL_OPT,*argv);
}
}
}
if(n_val == 0) /* Set "n_val" if not given */
n_val = 100;
/* Get the input data */
while(1) /* ... while there is more input data */
{
if(aflag == TRUE) /* Automatic abscissae were called for */
{
if(n == 0)
x[0] = x1_val;
else
x[n] = x[n-1] + a_val;
}
else /* Abscissae supplied with input data */
{
if(gets(buffer))
x[n] = atof(buffer);
else
break;
}
if(gets(buffer)) /* Read in the corresponding ordinate */
y[n] = atof(buffer);
else
{
if(aflag == TRUE)
break;
else
error(MIS_YVL,NULL);
}
if(++n == MAX_SIZE) /* Max